package com.ruoyi.recycle.service.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.core.constant.HttpStatus;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.recycle.constant.OrderInfoConstant;
import com.ruoyi.recycle.domain.*;
import com.ruoyi.recycle.dto.ClientWithDrawDTO;
import com.ruoyi.recycle.dto.MyAccountDTO;
import com.ruoyi.recycle.dto.PaymentDTO;
import com.ruoyi.recycle.dto.SubordinateDTO;
import com.ruoyi.recycle.mapper.ClientAddressMapper;
import com.ruoyi.recycle.mapper.ClientUserManagementMapper;
import com.ruoyi.recycle.mapper.RecycleOrderMapper;
import com.ruoyi.recycle.service.*;
import com.ruoyi.recycle.utils.MiniProgramUtil;
import com.ruoyi.recycle.utils.OrderNoGenerateUtil;
import com.ruoyi.recycle.vo.SubordinateVO;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

import static com.ruoyi.common.core.utils.PageUtils.startPage;

/**
 * 普通用户管理Service业务层处理
 *
 * @author Wubk
 * @date 2022-05-21
 */
@Service
public class ClientUserManagementServiceImpl extends ServiceImpl<ClientUserManagementMapper, ClientUserManagement> implements IClientUserManagementService {
    @Autowired
    private ClientUserManagementMapper clientUserManagementMapper;
    @Resource
    private ClientAddressMapper clientAddressMapper;
    @Autowired
    private OrderNoGenerateUtil orderNoGenerateUtil;
    @Resource
    private IIntegralConfigService iIntegralConfigService;
    @Resource
    private ExchangeRecordService exchangeRecordService;
    @Resource
    private WechatPaymentService paymentService;
    @Resource
    private BillRecordService billRecordService;
    @Resource
    private IFinanceManagementService financeManagementService;
    @Resource
    private RecycleOrderMapper recycleOrderMapper;

    /**
     * 查询普通用户管理
     *
     * @param id 普通用户管理主键
     * @return 普通用户管理
     */
    @Override
    public ClientUserManagement selectClientUserManagementById(Long id) {
        return clientUserManagementMapper.selectClientUserManagementById(id);
    }

    /**
     * 查询普通用户管理列表
     *
     * @param clientUserManagement 普通用户管理
     * @return 普通用户管理
     */
    @Override
    public List<ClientUserManagement> selectClientUserManagementList(ClientUserManagement clientUserManagement) {
        return clientUserManagementMapper.selectClientUserManagementList(clientUserManagement);
    }

    /**
     * 新增普通用户管理
     *
     * @param clientUserManagement 普通用户管理
     * @return 结果
     */
    @Override
    public int insertClientUserManagement(ClientUserManagement clientUserManagement) {
        return clientUserManagementMapper.insertClientUserManagement(clientUserManagement);
    }

    /**
     * 修改普通用户管理
     *
     * @param clientUserManagement 普通用户管理
     * @return 结果
     */
    @Override
    public int updateClientUserManagement(ClientUserManagement clientUserManagement) {
        return clientUserManagementMapper.updateClientUserManagement(clientUserManagement);
    }

    /**
     * 批量删除普通用户管理
     *
     * @param ids 需要删除的普通用户管理主键
     * @return 结果
     */
    @Override
    public int deleteClientUserManagementByIds(Long[] ids) {
        return clientUserManagementMapper.deleteClientUserManagementByIds(ids);
    }

    /**
     * 删除普通用户管理信息
     *
     * @param id 普通用户管理主键
     * @return 结果
     */
    @Override
    public int deleteClientUserManagementById(Long id) {
        return clientUserManagementMapper.deleteClientUserManagementById(id);
    }

    /**
     * 添加积分
     *
     * @param id
     * @param integral
     * @return
     */
    @Override
    public AjaxResult saveIntegral(Long id, Long integral) {

        ClientUserManagement clientUserManagement = clientUserManagementMapper.selectClientUserManagementById(id);

        clientUserManagement.setIntegral(clientUserManagement.getIntegral() == null ? integral : clientUserManagement.getIntegral() + integral);
        clientUserManagementMapper.updateById(clientUserManagement);
        return AjaxResult.success();
    }

    /**
     * 获取客户地址列表
     *
     * @param clientId
     * @return
     */
    @Override
    public AjaxResult getClientAddress(Integer clientId) {

        LambdaQueryWrapper<ClientAddress> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(ClientAddress::getClientId, clientId);

        List<ClientAddress> clientAddresses = clientAddressMapper.selectList(queryWrapper);

        return AjaxResult.success(clientAddresses);
    }


    @Override
    public AjaxResult addAddress(ClientAddress clientAddress) {
        List<ClientAddress> addressList = clientAddressMapper.selectList(
                new LambdaQueryWrapper<ClientAddress>().
                        eq(ClientAddress::getClientId, clientAddress.getClientId()).
                        eq(ClientAddress::getAddress, clientAddress.getAddress()).
                        eq(ClientAddress::getPhone, clientAddress.getPhone()));
        if (addressList.size()>0){
            return AjaxResult.success("已存在相同的详细地址与对应手机号码，自动跳过");
        }
        clientAddressMapper.insert(clientAddress);
        return AjaxResult.success();
    }

    @Override
    public AjaxResult updateAddress(ClientAddress clientAddress) {

        if (clientAddress.getStatus() == 1) {
            //默认地址只可能存在一个
            clientAddressMapper.updateAddressStatus(clientAddress.getClientId());
        }

        clientAddressMapper.updateById(clientAddress);
        return AjaxResult.success();
    }

    @Override
    public AjaxResult deleteAddress(Long[] ids) {
        clientAddressMapper.deleteBatchIds(Arrays.asList(ids));
        return AjaxResult.success();
    }

    @Override
    public AjaxResult getAddress(Long clientId) {
        return AjaxResult.success(clientAddressMapper.selectById(clientId));
    }

    @Override
    public Map<String, List<ClientUserManagement>> clientGroupBySalesman(LambdaQueryWrapper queryWrapper) {
        return getBaseMapper().clientGroupBySalesman(queryWrapper);
    }

    @Override
    public AjaxResult login(String code) {

        String result = "";

        String appId = "wxc097c5dcf8c9cf16";
        String secret = "f75025b2e55941f579ef625e1dc4886f";
        try {//请求微信服务器，用code换取openid。HttpUtil是工具类，后面会给出实现，Configure类是小程序配置信息，后面会给出代码
            result = HttpUtil.get("https://api.weixin.qq.com/sns/jscode2session?appid="
                    + appId + "&secret="
                    + secret + "&js_code="
                    + code
                    + "&grant_type=authorization_code");
        } catch (Exception e) {
            e.printStackTrace();
        }
        Map<String, Object> map = new HashMap<>();
        JSONObject jsonObj = JSONUtil.parseObj(result);//解析从微信服务器上获取到的json字符串
        String openId = (String) jsonObj.get("openid");
        if (StringUtils.isBlank(openId)) {
            return AjaxResult.error("请登录");
        }
        System.out.println("用户的openid为：" + jsonObj.get("openid"));//此处也可以得到session_key的值
        map.put("session_key", jsonObj.get("session_key").toString());
        //这里Miniuser类是自己的业务类，你可以根据自己需要自行定义

        LambdaQueryWrapper<ClientUserManagement> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ClientUserManagement::getOpenid, jsonObj.get("openid").toString());
        List<ClientUserManagement> clientEntityList = list(queryWrapper);
        map.put("openid", jsonObj.get("openid"));//将用户id返回

        if (CollUtil.isEmpty(clientEntityList))//如果不存在该用户
        {
            map.put("validity", "NO");//告知是未注册用户
            return AjaxResult.success(map);
        }

        return AjaxResult.success(map);
    }


    @Override
    public AjaxResult charge(PaymentDTO paymentDTO) {
        try {
            final String chargeOrderNo = orderNoGenerateUtil.getIncr(OrderInfoConstant.CHARGE_ORDER);
            final IntegralConfig integralConfig = iIntegralConfigService.getOne(Wrappers.lambdaQuery(new IntegralConfig())
                    .eq(IntegralConfig::getType, "充值"));
            paymentDTO.setOrderNo(chargeOrderNo);
            final ClientUserManagement client = this.getOne(Wrappers.lambdaQuery(new ClientUserManagement())
                    .eq(ClientUserManagement::getOpenid, paymentDTO.getOpenId()));
            this.updateById(client.setIntegral(client.getIntegral() + paymentDTO.getTotalFee().longValue()));
            exchangeRecordService.save(new ExchangeRecord()
                    .setAmount(paymentDTO.getTotalFee())
                    .setOrderNo(chargeOrderNo)
                    .setAccount(paymentDTO.getAccount())
                    .setType("充值")
                    .setExchangeStatus("支付中")
                    .setSource("客户"));
            final Map<String, String> paymentFeedback = paymentService.pay(paymentDTO);
            billRecordService.save(new BillRecord().setIncome(paymentDTO.getTotalFee()
                    .multiply(BigDecimal.valueOf(integralConfig.getIntegral())))
                    .setOrderNo(chargeOrderNo)
                    .setType(0));
            return AjaxResult.success(paymentFeedback);
        } catch (Exception e) {
            final String message = e.getMessage();
            Map<String, String> errorMap = new HashMap<>();
            errorMap.put("充值失败", "500");
            errorMap.put("原因", message);
            return AjaxResult.error().put("result", errorMap);
        }

    }


    @Override
    public AjaxResult withDraw(ClientWithDrawDTO withDrawDTO) {
        final IntegralConfig integralConfig = iIntegralConfigService.getOne(Wrappers.lambdaQuery(new IntegralConfig())
                .eq(IntegralConfig::getType, 1));
        final ClientUserManagement clientUserManagement = this.getOne(Wrappers.lambdaQuery(new ClientUserManagement())
                .eq(ClientUserManagement::getOpenid, withDrawDTO.getAccount()));
        final BigDecimal integralDV = BigDecimal.valueOf(clientUserManagement.getIntegral());
        final Long balance = integralDV.subtract(withDrawDTO.getAmount()).longValue();
        this.updateById(clientUserManagement.setIntegral(balance));
        final BigDecimal amount = withDrawDTO.getAmount()
                .divide(BigDecimal.valueOf(integralConfig.getIntegral()), 2, BigDecimal.ROUND_HALF_DOWN);
        String withDrawOrderNo = orderNoGenerateUtil.getIncr(OrderInfoConstant.WITHDRAW_ORDER);
        exchangeRecordService.save(new ExchangeRecord()
                .setExchangeStatus("待处理")
                .setType("提现")
                .setAccount(withDrawDTO.getAccount())
                .setAmount(amount)
                .setOrderNo(withDrawOrderNo)
                .setOrderBatchNo(orderNoGenerateUtil.getIncr(OrderInfoConstant.ORDER_BATCH_NO))
                .setSource("客户"));
        billRecordService.save(new BillRecord().setOutput(amount)
                .setOrderNo(withDrawOrderNo).setUserId(clientUserManagement.getId()).setUserType(1)
                .setType(3));
        financeManagementService.save(new FinanceManagement()
                .setCreatedBy(withDrawDTO.getAccount())
                .setOrderNumber(withDrawOrderNo)
                .setPhone(clientUserManagement.getPhone())
                .setStatus("待审核")
                .setUserName(clientUserManagement.getUserName())
                .setWithdrawIntegral(withDrawDTO.getAmount().longValue())
                .setWithdrawMoney(amount)
                .setWithdrawType("微信")
                .setCreatedTime(new Date())
                .setCreatedBy(clientUserManagement.getUserName()));
        return AjaxResult.success("已发起提现申请");
    }

    @Override
    public AjaxResult myHome(Long clientId) {

        //获取个人首页信息
        ClientUserManagement clientUserManagement = clientUserManagementMapper.selectById(clientId);
        if(ObjectUtils.isEmpty(clientUserManagement)){
            return AjaxResult.error("服务器异常，请关闭小程序重新打开");
        }
        if (StringUtils.isBlank(clientUserManagement.getImg())){
            ClientUserManagement byId = getById(0);
            clientUserManagement.setImg(byId.getImg());
        }

        //减碳总值
        Double sum = recycleOrderMapper.carbonReductionSum(clientId);

        Integer floor = 0;
        if (sum != null) {
            floor = (int) Math.floor(sum / 1000);
        }

        return AjaxResult.success(clientUserManagement).put("CarbonReduction",sum).put("medal",floor);
    }

    @Override
    public AjaxResult generatePoster(Integer userId,Integer userType) {

        String miniqrQr = MiniProgramUtil.postMiniqrQr("userId="+userId+",userType="+userType, "pages/index/index", MiniProgramUtil.getToken("wxc097c5dcf8c9cf16","f75025b2e55941f579ef625e1dc4886f"));
        if (userType == 1) {
            ClientUserManagement clientUserManagement = clientUserManagementMapper.selectById(userId);
            clientUserManagement.setImg(miniqrQr);
            clientUserManagementMapper.updateClientUserManagement(clientUserManagement);
        }

        return AjaxResult.success(miniqrQr);
    }

    @Override
    public AjaxResult carbonReduction(Integer clientId) {

        List<Map<String,String>> carbonReduction = recycleOrderMapper.carbonReduction(clientId);

        return AjaxResult.success(carbonReduction);
    }

    @Override
    public AjaxResult mySubordinate(SubordinateDTO subordinateDTO) {
        //达人总拉新
        Integer countMan = clientUserManagementMapper.selectCount(new LambdaQueryWrapper<ClientUserManagement>().eq(ClientUserManagement::getSuperiorId, subordinateDTO.getClientId()));
        //达人总订单
        Integer countOrder =  clientUserManagementMapper.selectSubordinateOrderCount(subordinateDTO.getClientId());
        //统计列表
        startPage();
        List<SubordinateVO> subordinateVOList = clientUserManagementMapper.mySubordinate(subordinateDTO);
        TableDataInfo dataTable = getDataTable(subordinateVOList);
        return AjaxResult.success(dataTable).put("countMan",countMan).put("countOrder",countOrder);
    }

    @Override
    public AjaxResult myAccount(MyAccountDTO myAccountDTO) {
        //获取当前剩余总积分
        ClientUserManagement clientUserManagement = this.getById(myAccountDTO.getClientId());

        //获取总支出积分
        Long outIntegral = billRecordService.selectCountOutIntegral(myAccountDTO.getClientId(),myAccountDTO.getSearchTime());

        //获取总获得积分
        Long InIntegral = billRecordService.selectCountInIntegral(myAccountDTO.getClientId(),myAccountDTO.getSearchTime());

        //获取积分明细（默认全获取）
        List<BillRecord> list = billRecordService.getBillRecordList(myAccountDTO.getClientId(),myAccountDTO.getSearchTime());

        return AjaxResult.success(list).
                put("totalIntegral",clientUserManagement.getIntegral()).
                put("totalOutIntegral",outIntegral==null?0:outIntegral).
                put("totalInIntegral",InIntegral==null?0:InIntegral);
    }


    @Override
    public AjaxResult myHomeByClientId(String openid,String clientType) {
        //获取个人首页信息
        ClientUserManagement clientUserManagement = clientUserManagementMapper.selectOne(new LambdaQueryWrapper<ClientUserManagement>().eq(ClientUserManagement::getOpenid,openid).eq(ClientUserManagement::getClientType,clientType));
        if(ObjectUtils.isEmpty(clientUserManagement)){
            return AjaxResult.error("服务器异常，请关闭小程序重新打开");
        }
        if (StringUtils.isBlank(clientUserManagement.getImg())){
            ClientUserManagement byId = getById(0);
            clientUserManagement.setImg(byId.getImg());
        }

        //减碳总值
        Double sum = recycleOrderMapper.carbonReductionSum(clientUserManagement.getId());
        //环保勋章
        Integer floor = 0;
        if (sum != null) {
            floor = (int) Math.floor(sum / 1000);
        }
        return AjaxResult.success(clientUserManagement).put("CarbonReduction",sum).put("medal",floor);
    }

    protected TableDataInfo getDataTable(List<?> list) {
        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(HttpStatus.SUCCESS);
        rspData.setRows(list);
        rspData.setMsg("查询成功");
        rspData.setTotal(new PageInfo(list).getTotal());
        return rspData;
    }
}
